package com.tbit.uqbike.webmanager.controller;

import com.github.pagehelper.PageHelper;
import com.tbit.common.utils.TraceUtil;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.PageData;
import com.tbit.uqbike.object.business.SugarPost;
import com.tbit.uqbike.object.business.UserInfo;
import com.tbit.uqbike.object.pojo.MachineStatusFlag;
import com.tbit.uqbike.object.pojo.statistics.ExportMachine;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.rpcservice.MachineManagerService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.controller.interceptor.HttpHeadName;
import com.tbit.uqbike.webmanager.controller.interceptor.LanguageInterceptor;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import com.tbit.uqbike.webmanager.util.StringUtils;
import com.tbit.uqbike.webmanager.util.excel.ExportExcelUtil;
import com.tbit.uqbike.webmanager.util.excel.ExportExcelWrapper;
import com.tbit.uqbike.webmanager.util.page.PageDomain;
import com.tbit.uqbike.webmanager.util.page.TableSupport;
import com.tbit.uqbike.webmanager.util.sql.SqlUtil;
import com.tbit.utils.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.RequestContext;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * created by Kang on 2019/4/1 16:30
 * description:基础类
 */
public abstract class BaseController {
    // 内容格式定义
    public static final String MEDIA_JSON_UTF8 = "application/json; charset=utf-8";
    public static final String MEDIA_OCTET = "application/octet-stream";

    // sessionid 到 用户信息的映射，免得重复创建对象
    private static final ConcurrentHashMap<String, LoginInfo> sid2Info = new ConcurrentHashMap<>();

    private static final ReentrantLock _lock = new ReentrantLock();
    @Autowired
    private TokenService tokenService;
    @Resource
    private PurviewService purviewService;

    public static void delSid(String sid) {
        sid2Info.remove(sid);
    }

    /**
     * 获取当前登录用户信息
     *
     * @param request
     * @return
     */
    public static LoginInfo getLogin(HttpServletRequest request) {
        // 补全用户信息，语言和时区从属性中获取
        LoginInfo info = (LoginInfo) request.getAttribute(HttpHeadName.REQUEST_ATTR_NAME_USER);
        if (info == null) {
            // 此处根据session来
            String sid = request.getSession().getId();
            try {
                _lock.lock();
                sid2Info.put(sid, new LoginInfo());
            } finally {
                _lock.unlock();
            }

            info = sid2Info.get(sid);
        }

        info.refreshZoneAndLang(getAttrString(request, HttpHeadName.REQUEST_ATTR_NAME_LANG),
                getAttrString(request, HttpHeadName.REQUEST_ATTR_NAME_ZONE));
        info.context = new RequestContext(request);
        return info;
    }

    private static Object getAttrString(HttpServletRequest request, String name) {
        Object value = request.getAttribute(name);
        return value;
    }

    public LoginInfo getLogin(HttpServletRequest request, SugarPost sugarPost) {
        // 刷新token
        if (null == sugarPost || sugarPost.querys == null || null == sugarPost.querys.token) {
            throw new BaseException(SystemCodeEnum.TOKEN_EXPIRE);
        }
        LoginInfo info = tokenService.getLoginInfo(sugarPost.querys.token);
        request.setAttribute(HttpHeadName.REQUEST_ATTR_NAME_USER, info);
        if (info == null) {
            throw new BaseException(SystemCodeEnum.TOKEN_EXPIRE);
        }
        Locale locale;
        if (sugarPost.querys.lang == null) {
            locale = LanguageInterceptor.CN_LOCAL;
        } else {
            locale = LanguageInterceptor.parseLocaleValue(sugarPost.querys.lang);
        }

        Integer zone = LanguageInterceptor.parseZone(sugarPost.querys.zone);
        info.refreshZoneAndLang(locale, zone);
        info.context = new RequestContext(request);
        info.context.changeLocale(locale);
        return info;
    }

    protected void export(PageData<List<MachineStatusFlag>> pageDatas, MachineManagerService machineManagerService, HttpServletResponse response) {
        RequestContext context = getLogin(ServletUtils.getRequest()).getContext();
        List<ExportMachine> exports = machineManagerService.export(pageDatas, context);
        ExportExcelWrapper<ExportMachine> util = new ExportExcelWrapper<>();
        String filename = context.getMessage("machine_list") + DateTimeUtil.getNowTimeYMD();
        String[] columnNames = {context.getMessage("machine_type"), context.getMessage("excel.col.userCode"),
                context.getMessage("excel.col.machineNO"), context.getMessage("machine_status"),
                context.getMessage("online_status"), context.getMessage("last_position_time"),
                context.getMessage("last_borrow_time"), "所属站点",
                context.getMessage("excel.col.frame"), context.getMessage("excel.col.license"), context.getMessage("excel.col.motor")};
        util.exportExcel(filename, filename, columnNames, exports, response, ExportExcelUtil.EXCEL_FILE_2003);
    }

    //,context.getMessage("excel_head_site_regionId"),
//        context.getMessage("excel_head_site_regionName")
    protected JsonResult toAjax(Object data) {
        if (data == null) {
            return JsonResult.fail("地址解析失败", TraceUtil.getTraceIdByLocal());
        } else {
            return JsonResult.ok(data);
        }
    }

    /**
     * 设置请求分页数据
     */
    protected void startPage() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNO = pageDomain.getPageNO();
        Integer rowCount = pageDomain.getRowCount();
        if (StringUtils.isNotNull(pageNO) && StringUtils.isNotNull(rowCount)) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.startPage(pageNO, rowCount, orderBy);
        }
    }

    /**
     * 设置请求分页数据
     */
    protected List startPage(List data) {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNO = pageDomain.getPageNO();
        Integer rowCount = pageDomain.getRowCount();
        /**如果没传页码，默认给页码值*/
        if (StringUtils.isNull(pageNO) && StringUtils.isNull(rowCount)) {
            pageNO = 1;
            rowCount = 10;
        }
        int start = (pageNO - 1) * rowCount;
        int end = pageNO * rowCount;
        if (start > data.size()) {
            data = new ArrayList();
        } else if (end <= data.size()) {
            data = data.subList(start, end);
        } else {
            data = data.subList(start, data.size());
        }
        return data;
    }

    public void validateAccountPermissions(HttpServletRequest request, Integer accessAccountId) {
        LoginInfo loginInfo = getLogin(request);
        if (loginInfo.roleNotAdmin()) {
            if (!purviewService.purviewCheck(loginInfo.getId(), accessAccountId)) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }
    }

    public static UserInfo fetchUserInfo(){
        HttpServletRequest request =
                ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        LoginInfo loginInfo = getLogin(request);
        return UserInfo.builder()
                       .accountUserId(loginInfo.getAccountUserId())
                       .phone(loginInfo.getPhone())
                       .name(loginInfo.getName())
                       .build();
    }

}
